Skip to content

Revert "refactor: use Cmd class for hook command execution"#1690

Closed
dengbo11 wants to merge 1 commit into
OpenAtom-Linyaps:masterfrom
dengbo11:revert-hook
Closed

Revert "refactor: use Cmd class for hook command execution"#1690
dengbo11 wants to merge 1 commit into
OpenAtom-Linyaps:masterfrom
dengbo11:revert-hook

Conversation

@dengbo11

Copy link
Copy Markdown
Collaborator

This reverts commit 9e3220f.

@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengbo11

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@dengbo11 dengbo11 requested a review from reddevillg June 24, 2026 14:31

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the custom Cmd execution mechanism in executeHookCommands with std::system and uses EnvironmentVariableGuard to manage environment variables. It also introduces a helper function escapeAndWrapCommandForShell to escape and wrap command strings. Feedback on this PR highlights a critical bug in escapeAndWrapCommandForShell where the command string is not wrapped in single quotes, which breaks commands with arguments when passed to sh -c. The reviewer suggested either removing the redundant sh -c wrapping entirely (since std::system already invokes the shell) or properly wrapping the escaped command in single quotes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +37 to +48
static std::string escapeAndWrapCommandForShell(const std::string &command)
{
std::string escapedCommand = command;
size_t pos = 0;
// Replace ' with '\'' (close current quote, add literal single quote, open new quote)
while ((pos = escapedCommand.find('\'', pos)) != std::string::npos) {
escapedCommand.replace(pos, 1, "'\\''");
pos += 4;
}

return "sh -c " + escapedCommand;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The escapeAndWrapCommandForShell function is missing single quotes around the command string in its return statement. Currently, it returns "sh -c " + escapedCommand.

Without single quotes, a command with arguments (e.g., echo foo bar) is passed to std::system as sh -c echo foo bar. The outer shell executes sh -c echo foo bar, which runs sh with -c and echo as the command string, treating foo and bar as positional parameters ($0, $1) for the inner shell. Since the command string echo does not reference these positional parameters, they are completely ignored, and the command runs without arguments (e.g., printing an empty line instead of foo bar). This completely breaks any hook command that contains arguments.

Recommended Solutions:

  1. Simplest & Best Approach: Completely remove escapeAndWrapCommandForShell and pass command_raw directly to std::system. Since std::system already executes the command string by invoking /bin/sh -c, wrapping it in another sh -c is redundant, spawns an extra shell process, and introduces unnecessary escaping complexity.

  2. Alternative (if explicit wrapping is required): Wrap the escaped command in single quotes as shown in the suggestion below.

Suggested change
static std::string escapeAndWrapCommandForShell(const std::string &command)
{
std::string escapedCommand = command;
size_t pos = 0;
// Replace ' with '\'' (close current quote, add literal single quote, open new quote)
while ((pos = escapedCommand.find('\'', pos)) != std::string::npos) {
escapedCommand.replace(pos, 1, "'\\''");
pos += 4;
}
return "sh -c " + escapedCommand;
}
static std::string escapeAndWrapCommandForShell(const std::string &command)
{
std::string escapedCommand = command;
size_t pos = 0;
// Replace ' with '\'' (close current quote, add literal single quote, open new quote)
while ((pos = escapedCommand.find('\'', pos)) != std::string::npos) {
escapedCommand.replace(pos, 1, "'\\''");
pos += 4;
}
return "sh -c '" + escapedCommand + "'";
}

@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

deepin pr auto review

★ 总体评分:20分

■ 【总体评价】

代码尝试优化环境变量管理并重构命令执行逻辑,但引入了严重的命令注入与双重Shell嵌套漏洞
逻辑错误且存在严重命令注入风险,根据安全优先原则强制降至20分

■ 【详细分析】

  • 1.语法逻辑(存在严重错误)✕

escapeAndWrapCommandForShell 函数在 libs/utils/src/linglong/utils/hooks.cpp 中存在双重 sh -c 嵌套逻辑错误。std::system 底层已通过 execl("/bin/sh", "sh", "-c", ...) 调用,而该函数返回值又拼接了 "sh -c ",导致实际执行时变成外层 sh -c "sh -c ...",造成无意义的进程嵌套与参数解析混乱。
潜在问题:双重 sh -c 嵌套导致命令解析行为异常;缺少单引号包裹导致含空格或分号的命令被外层 Shell 错误拆分
建议:移除函数中多余的 "sh -c " 拼接逻辑,直接返回转义后的安全字符串

  • 2.代码质量(存在严重问题)✕

代码注释声明 This function ensures the command string is safely wrapped for 'sh -c',但实际实现既不安全也未正确包裹,属于严重的文档与实现不符。虽然引入了 EnvironmentVariableGuard 进行环境变量生命周期管理,思路良好,但核心执行逻辑的劣化导致整体质量极差。
潜在问题:注释与实现完全脱节;废弃了原本安全的 Cmd 类参数数组传递方式,采用了极易出错的字符串拼接方式
建议:回退至使用 Cmd 类直接传递参数数组,或彻底重写转义包裹逻辑并更正注释

  • 3.代码性能(存在性能问题)✕

由于双重 sh -c 嵌套,每次执行 Hook 命令都会额外派生一个多余的 Shell 进程,造成不必要的进程创建与销毁开销。
潜在问题:无意义的额外 Shell 进程派生增加了系统调度与内存开销
建议:去除多余的 sh -c 拼接,避免双重进程派生

  • 4.代码安全(存在 1 个安全漏洞)✕

漏洞对比统计:新增漏洞 1 个,减少漏洞 0 个,持平 0 个
代码在命令拼接时未使用单引号保护,导致外部传入的特殊字符直接被宿主 Shell 解释,攻击面极大

  • 安全漏洞1(【严重】):命令注入 在 libs/utils/src/linglong/utils/hooks.cppescapeAndWrapCommandForShell 函数中,当传入的 Hook 命令包含分号、反引号、$() 等特殊字符时,由于返回值 "sh -c " + escapedCommand 缺少单引号包裹,且 std::system 会唤起外层 Shell,特殊字符会被外层 Shell 直接解析执行,导致攻击者可绕过内层命令限制,执行任意恶意系统命令 ——非常重要

  • 建议:若必须使用 std::system,应将转义后的命令用单引号严格包裹,并移除多余的 sh -c 拼接;强烈建议恢复使用 Cmd 类以参数数组形式传参,从根本上阻断 Shell 注入

■ 【改进建议代码示例】

diff --git a/libs/utils/src/linglong/utils/hooks.cpp b/libs/utils/src/linglong/utils/hooks.cpp
index e4eb8d06e..fixed_version 100644
--- a/libs/utils/src/linglong/utils/hooks.cpp
+++ b/libs/utils/src/linglong/utils/hooks.cpp
@@ -35,16 +35,15 @@ constexpr std::string_view POST_UNINSTALL_ACTION_PREFIX = "ll-post-uninstall=";
 
 // This function ensures the command string is safely wrapped for execution via std::system.
 static std::string escapeAndWrapCommandForShell(const std::string &command)
 {
     std::string escapedCommand = command;
     size_t pos = 0;
     // Replace ' with '\'' (close current quote, add literal single quote, open new quote)
     while ((pos = escapedCommand.find('\'', pos)) != std::string::npos) {
         escapedCommand.replace(pos, 1, "'\\''");
         pos += 4;
     }
-
-    return "sh -c " + escapedCommand;
+    // std::system 底层自带 sh -c,直接返回被单引号包裹的安全命令即可
+    return "'" + escapedCommand + "'";
 }
 
 using CommandList = const std::vector<std::string> &;

@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

@dengbo11: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
github-pr-review-ci 8d07265 link true /test github-pr-review-ci

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
libs/utils/src/linglong/utils/hooks.cpp 0.00% 24 Missing ⚠️
Files with missing lines Coverage Δ
libs/utils/src/linglong/utils/hooks.cpp 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dengbo11 dengbo11 closed this Jun 25, 2026
@dengbo11 dengbo11 deleted the revert-hook branch July 1, 2026 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants